package com.freecloud.whispered.auth.oauth2;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.freecloud.framework.config.ClientConfig;
import com.freecloud.framework.constant.Constant;
import com.freecloud.framework.utils.DESUtils;
import com.freecloud.framework.utils.SpringContextUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import static com.freecloud.framework.constant.Constant.CLOUD_APP_PERMISSIONS_ALL;

/**
 * 内部业务调用授权
 * @Author: maomao
 * @Date: 2019-08-11 21:57
 */
@Component
public class ClientOAuth2Realm extends AuthorizingRealm {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof ClientOAuth2Token;
    }

    /**
     * 授权(验证权限时调用)
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(CLOUD_APP_PERMISSIONS_ALL);
        return info;
    }

    /**
     * 认证(登录时调用)
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String accessToken = (String) token.getPrincipal();

        if(StrUtil.isEmpty(accessToken)){
            throw new IncorrectCredentialsException("client token不允许为空");
        }
        String password = DESUtils.decode(Constant.CLIENT_TOKEN_PASSWORD_KEY,accessToken);
        if(StrUtil.isEmpty(password)){
            throw new IncorrectCredentialsException("无效果的client token");
        }

        String[] arr = password.split(Constant.CLIENT_TOKEN_PASSWORD_PARTITION);

        //根据token反序列化，获取到时间戳，根据时间戳校验失效时间
        if(!NumberUtil.isLong(arr[arr.length - 1])){
            logger.error("解析client token错误：{} ----- {}",accessToken,password);
            throw new IncorrectCredentialsException("无效果的client token");
        }

        ClientConfig clientConfig = SpringContextUtils.getBean(ClientConfig.class);

        Long time = NumberUtil.parseLong(arr[arr.length - 1]);
        Long currentTime = DateUtil.date().getTime();

        if(currentTime - time > clientConfig.getClientExpire()){
            logger.info("client token失效 : currentTime<{}> ------ token time<{}>-----clientExpire<{}>",currentTime,time,clientConfig.getClientExpire());
            throw new IncorrectCredentialsException("client token失效");
        }

        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(arr, accessToken, getName());
        return info;
    }
}
